package com.ecric.http.OkHttp3;

import android.os.Environment;
import android.util.Log;


import java.io.File;
import java.io.IOException;
import java.io.ObjectStreamException;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import okhttp3.Cache;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;

/**
 * 这个类针对OkHttp3的请求步骤进行分析
 * <h3>Description</h3>
 * TODO
 * <h3>Author</h3> luzhenbang
 * <h3>Date</h3> 04/04/2018 10:02
 * <h3>Copyright</h3> Copyright (c)2018 Shenzhen TL  Co., Ltd. Inc. All rights reserved.
 */
public class Http3Util {

    /** Json类型*/
    public static final String JSON  = "application/json; charset=utf-8";
    /** 图片*/
    private static final MediaType MEDIA_TYPE_PNG = MediaType.parse("image/png");

    public static final String cache_file = "";
    public static OkHttpClient  client;


    private Http3Util(){

    }


    public static Http3Util getInstance() {
        getClient();
        return HttP3UtilHelp.http3Util;
    }


    /**
     * 第一步创建请求客户端
     * @return
     */
    private static OkHttpClient getClient(){
        int cacheSize = 10 * 1024 * 1024; // 10 MiB
        /**
         * 为了缓存响应，你需要一个你可以读写的缓存目录，和缓存大小的限制。这个缓存目录应该是私有的，不信任的程序应不能读取缓存内容。
         * 一个缓存目录同时拥有多个缓存访问是错误的。大多数程序只需要调用一次new OkHttpClient()，在第一次调用时配置好缓存，
         * 然后其他地方只需要调用这个实例就可以了。否则两个缓存示例互相干扰，破坏响应缓存，而且有可能会导致程序崩溃。
         * 一般情况下我们可以不使用缓存
         */
        Cache  cache = new Cache(new File(cache_file),cacheSize);
        OkHttpClient  client  = new OkHttpClient
                .Builder()
                .connectTimeout(10, TimeUnit.SECONDS)
                .readTimeout(10,TimeUnit.SECONDS)
                .writeTimeout(10, TimeUnit.SECONDS)
//                .cache(cache)
                .build();
        return client;
    }


    /**
     * 第二步：创建JSON请求体 请求的数据为json字符串
     * @return
     */
    public RequestBody getJsonBody( String json){
        MediaType mediaType = MediaType.parse(JSON);
        RequestBody  requestBody  = RequestBody.create(mediaType,json);
        return requestBody;
    }


    /**
     * 第二步：创建表单请求体 请求的数据为键值对(表单)  添加表单
     *
     * 很多时候我们会需要通过POST方式把键值对数据传送到服务器
     * @return
     */
    public RequestBody getFormBody (Map<String,Object> params){
        FormBody.Builder builder  = new FormBody.Builder();
        if (params != null  && params.size() > 0 ){
            Set<Map.Entry<String,Object>> entries = params.entrySet();
            Iterator<Map.Entry<String,Object>> iterator = entries.iterator();
            while (iterator.hasNext()){
                Map.Entry<String,Object> entry =  iterator.next();
                builder.add(entry.getKey(),String.valueOf(entry.getValue()));
            }
        }
        RequestBody  requestBody = builder.build();
        return requestBody;
    }



    /**
     * 第二步：创建多参(多块)请求体
     *
     * @return
     */
    public RequestBody getMultiBody (Map<String,Object> params){
        MultipartBody.Builder  builder = new MultipartBody.Builder();
        if (params != null  && params.size() > 0 ){
            Set<Map.Entry<String,Object>> entries = params.entrySet();
            Iterator<Map.Entry<String,Object>> iterator = entries.iterator();
            while (iterator.hasNext()){
                Map.Entry<String,Object> entry =  iterator.next();
                builder.addFormDataPart(entry.getKey(),String.valueOf(entry.getValue()));
            }
        }
        RequestBody  requestBody = builder.build();
        return requestBody;
    }



    /**
     * 第二步：创建文件请求体
     * @param files   需要上传的文件
     * @param keys 文件所对应的key值
     * @return
     */
    public RequestBody getFileBody (File[] files , String[] keys){
        MultipartBody.Builder  builder = new MultipartBody.Builder();
        if (files.length  == keys.length){
            for (int i = 0; i < files.length; i++) {
                builder.addFormDataPart(keys[i],files[i].getName(),RequestBody.create(MEDIA_TYPE_PNG,files[i]));
            }
        }
        RequestBody  requestBody = builder.build();
        return requestBody;
    }


    /**
     *  第三步创建请求类 post
     * @param url 服务器地址
     * @param requestBody 请求体
     * @return
     */
    public okhttp3.Request getRequest(String url,RequestBody requestBody){
        okhttp3.Request.Builder  builder = new okhttp3.Request.Builder();

        //请求报头
        builder.addHeader("Cache-Control","no-cache");//请求无缓存
        builder.addHeader("Accept-Language","zh-cn");//客户端可接受的语言
        builder.addHeader("Accept-Charset","UTF-8");//客户端可接受的字符集
        builder.addHeader("Accept-Encoding","gzip, deflate");//客户端可接受内容的编码格式
        builder.addHeader("Connection","Keep-Alive");
        builder.url(url)
                .post(requestBody);
        return builder.build();
    }



    /**
     *  第三步创建请求类 get
     * @param url 服务器地址
     * @return
     */
    public okhttp3.Request getRequest(String url){
        okhttp3.Request.Builder  builder = new okhttp3.Request.Builder();
        //请求报头
        builder.header("User-Agent","okHttp3/3.8 (android; v1.0)");//客户端信息
        builder.addHeader("Cache-Control","no-cache");//请求无缓存
        builder.addHeader("Accept-Language","zh-cn");//客户端可接受的语言
        builder.addHeader("Accept-Charset","UTF-8");//客户端可接受的字符集
        builder.addHeader("Accept-Encoding","gzip, deflate");//客户端可接受内容的编码格式
        builder.addHeader("Connection","Keep-Alive");
        builder.url(url).get();
        return builder.build();
    }


    /**
     *
     * 第四步：开始请求 异步请求
     */
    public void start (okhttp3.Request request){
        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                Log.e(Http3Util.class.getName() ,e.getMessage());
                Log.i(Http3Util.class.getName() ,e.getMessage());
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                dispose(response);
            }
        });
    }



    /**
     *
     * 第四步：开始请求 同步请求请求
     */
    public void startSyn(okhttp3.Request request){
        try {
            Response response  = client.newCall(request).execute();
            dispose(response);
        } catch (IOException e) {
            Log.e(Http3Util.class.getName() ,e.getMessage());
            Log.i(Http3Util.class.getName() ,e.getMessage());
        }
    }


    /**
     * 第五步：处理请求结果
     */

    public void dispose(Response response){
        if (response.isSuccessful()){
            ResponseBody body = response.body();
            try {
                String result  = body.string();

            } catch (IOException e) {
                Log.e(Http3Util.class.getName() ,e.getMessage());
                Log.i(Http3Util.class.getName() ,e.getMessage());
            }
        }else {

        }
    }


    private static class HttP3UtilHelp {
        private static Http3Util  http3Util = new Http3Util();
    }


    private Object readResolve() throws ObjectStreamException {
        return getInstance();
    }



}
